package com.rc.saas.mini.listener;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.rabbitmq.client.Channel;
import com.rc.saas.mini.common.base.TResponse;
import com.rc.saas.mini.common.mq.RabbitListenerConstant;
import com.rc.saas.mini.component.UidGenerator;
import com.rc.saas.mini.model.member.MemberInfo;
import com.rc.saas.mini.model.member.MemberRefundApply;
import com.rc.saas.mini.model.member.MemberRefundOrder;
import com.rc.saas.mini.model.order.OrderInfo;
import com.rc.saas.mini.model.recharge.RechargeOrder;
import com.rc.saas.mini.model.tenant.Tenant;
import com.rc.saas.mini.service.member.MemberInfoService;
import com.rc.saas.mini.service.member.MemberRefundOrderService;
import com.rc.saas.mini.service.order.OrderInfoService;
import com.rc.saas.mini.service.rc.RcOperatorAccountRecordService;
import com.rc.saas.mini.service.recharge.RechargeOrderService;
import com.rc.saas.mini.service.tenant.TenantService;
import com.rc.saas.mini.vo.charge.CommandStopReq;
import com.rc.saas.mini.weixin.WxSessionInfo;
import com.rc.saas.payment.wxpay.WXPayConstants;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.weixin4j.miniprogram.model.pay.ApplyRefundAmount;
import org.weixin4j.miniprogram.wxpay.sdk.WXMyConfigUtil;
import org.weixin4j.miniprogram.wxpay.sdk.WXPay;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

/**
 * @Author: yang
 * @CreateDate: 2022/9/5 22:55
 */
@Component
public class PaymentRefundOrderListener {
    private static Logger logger = LogManager.getLogger(PaymentRefundOrderListener.class);

    @Value("${weChat.refundNotifyUrl}")
    private String preRefundNotifyUrl;

    @Autowired
    private MemberRefundOrderService memberRefundOrderService;

    @Autowired
    private MemberInfoService memberInfoService;

    @Autowired
    private RechargeOrderService rechargeOrderService;

    @Autowired
    private TenantService tenantService;

    @Autowired
    private UidGenerator uidGenerator;

    @Autowired
    private OrderInfoService orderInfoService;

    //执行退款
    @RabbitListener(queues = RabbitListenerConstant.PAYMENT_REFUND_ORDER)
    public void paymentRefundOrderProcess(Message message, Channel channel) throws Exception {
        String msg = new String(message.getBody(), "UTF-8");
        logger.info("open2appNotifyStopChargeResultListener 收到了:{}", msg);

        CommandStopReq commandStopReq = new Gson().fromJson(msg, CommandStopReq.class);

        //订单信息
        OrderInfo orderInfo = orderInfoService.selectByPrimaryKey(commandStopReq.getOrderId());
        if (orderInfo == null || !"3".equals(orderInfo.getAccountType())) {
            return;
        }

        try {
            BigDecimal refundAmount = orderInfo.getRefundAmount();

            MemberRefundOrder memberRefundOrder = memberRefundOrderService.selectLast(orderInfo.getMemberId());
            if (memberRefundOrder == null) {
                logger.error("先付后退额度记录不存在，对应订单号:{}", orderInfo.getOrderNum());
            }
            if (!"17".equals(memberRefundOrder.getRecordType()) && !memberRefundOrder.getRefundType().equals("0")) {
                logger.error("先付后退额度记录不可退，对应订单号:{}", orderInfo.getOrderNum());
            }

            MemberInfo memberInfo = memberInfoService.selectByPrimaryKey(memberRefundOrder.getMemberId());
            Tenant tenant = tenantService.selectByTenantCode(memberRefundOrder.getTenantCode());

            String tenantCode = memberRefundOrder.getTenantCode();
            String mobile = memberInfo.getMobile();

            RechargeOrder rechargeOrder = rechargeOrderService.selectByTransactionId(memberRefundOrder.getOutOrderNum());
            if (rechargeOrder == null) {
                logger.error("paymentRefundOrderProcess.充值记录不存在,订单号:{},手机号码:mobile:{}", orderInfo.getOrderNum(), mobile);
                return;
            }

            //订单总金额，单位为分
            //交易金额默认为人民币交易，接口中参数支付金额单位为【分】，参数值不能带小数。对账单中的交易金额单位为【元】。
            //外币交易的支付金额精确到币种的最小单位，参数值不能带小数点
            BigDecimal targetAmount = refundAmount.multiply(new BigDecimal("100")).setScale(0, BigDecimal.ROUND_DOWN);
            if (targetAmount.compareTo(BigDecimal.ZERO) < 1) {
                logger.error("paymentRefundOrderProcess.factAmount金额不合法,订单号:{},手机号码:mobile:{}", orderInfo.getOrderNum(), mobile);
                return;
            }

            logger.info("saas微信支付退款:{},:{}", memberInfo.getMobile(), refundAmount);

            //根据不同的运营商简码生成充值订单号
            String outRefundNo = uidGenerator.genWxRechargeOutTradeNo(tenant.getTenantPrefix(), memberInfo.getMobile());

            //生成微信下单
            ApplyRefundAmount applyRefundAmount = new ApplyRefundAmount();
            applyRefundAmount.setAppid(tenant.getMinipAppid());
            applyRefundAmount.setMch_id(tenant.getWechatPayMchid());
            applyRefundAmount.setNonce_str(UUID.randomUUID().toString().replace("-", ""));
            //applyRefundAmount.setNonce_str("GmmtgsX8nkKtq954NqOBkk7MZY92VmFQ");
            applyRefundAmount.setNotify_url(preRefundNotifyUrl);
            applyRefundAmount.setOut_refund_no(outRefundNo); //商户退款订单号
            applyRefundAmount.setOut_trade_no(rechargeOrder.getOutTradeNo()); //充值本地订单号
            applyRefundAmount.setRefund_fee(refundAmount.multiply(new BigDecimal("100")).intValue() + "");   //正整数
            applyRefundAmount.setTotal_fee(memberRefundOrder.getFactAmount().multiply(new BigDecimal("100")).intValue() + ""); //正整数
            applyRefundAmount.setTransaction_id(rechargeOrder.getTransactionId());

            //签名
            logger.info("redisWxConfiguration.PartnerKey:{}", tenant.getWechatPaySecret());

            try {
                ObjectMapper objectMapper = new ObjectMapper();
                logger.info("订单信息 applyRefundAmount:{}", objectMapper.writeValueAsString(applyRefundAmount));

                //初始化weixin对象
                //Weixin weixin = new Weixin(tenant.getWechatOriginalid(), tenant.getWechatAppid(), tenant.getWechatSecret());
                WxSessionInfo wxSessionInfo = new WxSessionInfo();
                wxSessionInfo.setAppId(tenant.getMinipAppid());
                wxSessionInfo.setMchId(tenant.getWechatPayMchid());
                wxSessionInfo.setTenantCode(tenantCode);
                wxSessionInfo.setWechatPayMchid(tenant.getWechatPaySecret());

                WXMyConfigUtil wxMyConfigUtil = new WXMyConfigUtil(wxSessionInfo);
                WXPay wxPay = new WXPay(wxMyConfigUtil, preRefundNotifyUrl);
                //todo 调用微信退款接口
                Map<String, String> result = wxPay.refund(applyRefundAmount.toMap());

                logger.info("原路退款支付结果 result:{}", objectMapper.writeValueAsString(result));

                if (!result.get("result_code").equals(WXPayConstants.SUCCESS)) {
                    logger.error("退款失败,对应订单号:{},退款失败结果:{}", orderInfo.getOrderNum(), result.get("err_code_des"));
                    return;
                }

                //退款成功后, 生成预退款订单
                RechargeOrder order = new RechargeOrder();
                order.setTenantCode(wxSessionInfo.getTenantCode());
                order.setAmount(refundAmount);
                order.setFactAmount(refundAmount);
                order.setGiveAmount(BigDecimal.ZERO);
                order.setRechargeType("2");
                order.setOutTradeNo(outRefundNo);    //商户退款订单号
                order.setMemberId(memberInfo.getMemberId());
                order.setOldRechargeOrderId(rechargeOrder.getRechargeOrderId());//加入原充值订单号
                //支付方式 0:微信支付 1:支付宝
                order.setPaymentType("0");
                //到帐状态 0未到帐   1已到帐 默认0
                order.setStatus("0");
                //退款状态
                order.setIsRefund("1"); //退款
                order.setCreatedTime(new Date());
                order.setLastUpdatedTime(new Date());
                order.setCreatedBy(String.valueOf(memberInfo.getMemberId()));
                order.setLastUpdatedBy(String.valueOf(memberInfo.getMemberId()));
                rechargeOrderService.insertSelective(order);

                logger.info("退款成功:{}", applyRefundAmount.toMap());
                return;
            } catch (Exception e) {
                logger.error("微信退款异常", e);
            }
        } catch (Exception e) {
            logger.error("paymentRefundOrderProcess 错误", e);
        }
    }
}
